﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace TARLib
{
    /// <summary>
    /// Un nuovo ordine è il messaggio che viene inviato dalla cassa
    /// </summary>
    public class Ordine
    {
        #region Costruttori
        public Ordine(int userID, string autore)
        {
            OrdineID = Guid.NewGuid();
            UserID = userID;
            Autore = autore;
            DataOra = DateTime.Now;
            Comande = new ComandaCollection();
            Note = null;
            TavoloAssegnato = null;

            // Salva direttamente su DB (necessario per i prodotti Locked)
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_Ordine_I]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@OrdineID", System.Data.SqlDbType.UniqueIdentifier) { Value = OrdineID.Value });
            cmd.Parameters.Add(new SqlParameter("@UserID", System.Data.SqlDbType.Int) { Value = UserID });
            cmd.Parameters.Add(new SqlParameter("@TimeStamp_Insert", System.Data.SqlDbType.DateTime) { Value = DataOra });

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }
        }

        public Ordine(Guid? ordineID, int userID, string autore, DateTime dataOra, ComandaCollection comande, string note, string tavoloAssegnato)
        {
            OrdineID = ordineID;
            UserID = userID;
            DataOra = dataOra;
            Note = note;
            Comande = comande;
            TavoloAssegnato = tavoloAssegnato;
        }
        #endregion

        #region Proprietà
        public Guid? OrdineID { get; set; }
        public int UserID { get; set; }
        public string Autore { get; set; }
        public DateTime DataOra { get; set; }
        public ComandaCollection Comande { get; set; }
        public List<Comanda> ComandaList
        {
            get
            {
                List<Comanda> retList = new List<Comanda>();

                foreach (Comanda c in Comande)
                {
                    retList.Add(c);
                }

                return retList;
            }
        }
        private string _Note;
        public string Note
        {
            get
            {
                return _Note;
            }
            set
            {
                _Note = value;

                if (Comande != null)
                {
                    foreach (Comanda c in Comande)
                    {
                        c.Note = value;
                    }
                }
            }
        }

        private string _TavoloAssegnato;
        public string TavoloAssegnato
        {
            get
            {
                return _TavoloAssegnato;
            }
            set
            {
                _TavoloAssegnato = value;

                // Associa il tavolo a tutte le comande
                foreach (Comanda c in Comande)
                {
                    c.TavoloAssegnato = value;
                }
            }
        }
        #endregion

        #region Gestione prodotti (aggiunta/eliminazione)
        public KeyValuePair<ProdottoOrdinato, string> AggiungiProdotto(Prodotto prodottoDaAggiungere, Decimal prezzoVendita, string note)
        {
            KeyValuePair<ProdottoOrdinato, string> pOrd = Management.PrenotaProdotto(
                prodottoDaAggiungere,
                OrdineID.Value,
                prezzoVendita,
                note);

            if (pOrd.Key != null)
            {
                // Prenotazione effettuata
                // E' necessario creare una nuova comanda?
                if (Comande.Select(o => o.PuntoDiDistribuzione.PuntoDistribuzioneID).Contains(prodottoDaAggiungere.PuntoDiDistribuzione.PuntoDistribuzioneID))
                {
                    // Comanda per quel punto di distribuzione già presente
                    Comande.Where(o => o.PuntoDiDistribuzione.PuntoDistribuzioneID == prodottoDaAggiungere.PuntoDiDistribuzione.PuntoDistribuzioneID).First().Prodotti.Add(pOrd.Key);
                }
                else
                {
                    // Comanda non ancora presente
                    Comanda c = new Comanda(
                        null, // Attribuito in fase di salvataggio
                        new ProdottoOrdinatoCollection(),
                        pOrd.Key.PuntoDiDistribuzione.IsConsegnaRichiesta ? TavoloAssegnato : null,
                        null, // Attribuito in fase di salvataggio
                        Note,
                        0,
                        DataOra,
                        Autore,
                        null,
                        null,
                        null,
                        null,
                        null,
                        DataOra);
                    c.Prodotti.Add(pOrd.Key);
                    this.Comande.Add(c);
                }

                return pOrd;
            }
            else
            {
                // Prenotazione fallita: in value c'è il motivo
                return pOrd;
            }
        }

        public void AggiungiProdotto(ProdottoOrdinato prodottoDaAggiungere)
        {
            if (Comande.Select(o => o.PuntoDiDistribuzione.PuntoDistribuzioneID).Contains(prodottoDaAggiungere.PuntoDiDistribuzione.PuntoDistribuzioneID))
            {
                // Comanda per quel punto di distribuzione già presente
                Comande.Where(o => o.PuntoDiDistribuzione.PuntoDistribuzioneID == prodottoDaAggiungere.PuntoDiDistribuzione.PuntoDistribuzioneID).First().Prodotti.Add(prodottoDaAggiungere);
            }
            else
            {
                // Comanda non ancora presente
                Comanda c = new Comanda(
                    null, // Attribuito in fase di salvataggio
                    new ProdottoOrdinatoCollection(),
                    TavoloAssegnato,
                    null, // Attribuito in fase di salvataggio
                    Note,
                    0,
                    DataOra,
                    Autore,
                    null,
                    null,
                    null,
                    null,
                    null,
                    DataOra);
                c.Prodotti.Add(prodottoDaAggiungere);
                this.Comande.Add(c);
            }
        }

        public void RimuoviProdotto(ProdottoOrdinato prodottoOrdinatoDaRimuovere)
        {
            // Elimina il prodotto rimosso da DB
            if (prodottoOrdinatoDaRimuovere.CodiceOrdinazione.HasValue)
            {
                Management.EliminaPrenotazioneProdotto(prodottoOrdinatoDaRimuovere);
            }

            // Aggiorna le comande
            foreach (Comanda c in Comande.Where(o => o.Prodotti.Contains(prodottoOrdinatoDaRimuovere)))
            {
                c.Prodotti.Remove(prodottoOrdinatoDaRimuovere);
            }
            // Elimina comande "senza prodotti"
            for (int i = 0; i < Comande.Count; i++)
            {
                if (Comande[i].Prodotti.Count == 0)
                {
                    Comande.RemoveAt(i);
                    i--;
                }
            }
        }

        public void AzzeraPrenotazioni()
        {
            // Azzera tutti i prodotti prenotati da DB
            Management.EliminaTuttePrenotazioniProdotto(OrdineID.Value);

            // Aggiorna le comande
            Comande.Clear();
        }
        #endregion

        public Ordine Clona()
        {
            ComandaCollection cc = new ComandaCollection();
            foreach (Comanda c in Comande)
            {
                ProdottoOrdinatoCollection poc = new ProdottoOrdinatoCollection();
                foreach (ProdottoOrdinato po in c.Prodotti)
                {
                    poc.Add(new ProdottoOrdinato(
                        po.ProdottoID,
                        po.Nome,
                        po.NomeBreve,
                        po.CodiceOrdinazione,
                        po.PrezzoListino,
                        po.Note,
                        po.PrezzoVendita,
                        new PuntoDistribuzione(
                            po.PuntoDiDistribuzione.PuntoDistribuzioneID,
                            po.PuntoDiDistribuzione.Descrizione,
                            po.PuntoDiDistribuzione.IsCheckInRichiesto,
                            po.PuntoDiDistribuzione.IsStampaRemotaRichiesta,
                            po.PuntoDiDistribuzione.IsConsegnaRichiesta,
                            po.PuntoDiDistribuzione.IsTavoloRichiesto,
                            po.PuntoDiDistribuzione.PathStampante,
                            po.PuntoDiDistribuzione.VelocitaWidthFinestraSecondi,
                            po.PuntoDiDistribuzione.VelocitaNSuddivisioni,
                            po.PuntoDiDistribuzione.VelocitaLeftSkipPercentage,
                            po.PuntoDiDistribuzione.VelocitaRightSkipPercentage,
                            po.PuntoDiDistribuzione.GracePeriodStampaSecondi,
                            po.PuntoDiDistribuzione.VelocitaFissaProdottiOra),
                        po.CodiceProdottoBarcode,
                        po.IsLimitato,
                        po.PercentualeVassoio));
                }

                //ComandaLogCollection clc = new ComandaLogCollection();
                //foreach (ComandaLog cl in )
                //{

                //}

                cc.Add(new Comanda(
                    c.ComandaID,
                    poc,
                    c.TavoloAssegnato,
                    c.Codice,
                    c.Note,
                    c.Sconto,
                    c.DataOra,
                    c.Autore,
                    new ComandaLogCollection(),
                    c.CheckInAssociato,
                    c.StampaRemotaAssociata,
                    c.ConsegnaAssociata,
                    new VassoioCollection(),
                    c.TimeStampMinCheckIn));
            }

            return new Ordine(
                this.OrdineID,
                this.UserID,
                this.Autore,
                this.DataOra,
                cc,
                this.Note,
                this.TavoloAssegnato);
        }
    }
}